#pragma once
#include "nocopy.h"
#include <memory>
#include <string>
#include <atomic>
#include "InetAddress.h"
#include "Callbacks.h"
#include "Buffer.h"
#include "TimeStamp.h"

/**
 * TcpServer => Acceptor => 有一个新用户链接,通过Acceptor拿到connfd
 *
 * Tcpconnection通过设置回调=>将回调设置给Channel
 *
 * 然后Channel即将回调注册到Poller上,Poller监听到Channel的相应事件后进行回调操作
 *
 */
class Channel;
class EventLoop;
class Socket;
class TcpConnection : nocopyable, public std::enable_shared_from_this<TcpConnection>
{
public:
    TcpConnection(EventLoop *loop, const std::string &name, int socket, const InetAddress &localAddr,
                  const InetAddress &peerAddr);
    ~TcpConnection();
    EventLoop *getLoop() const
    {
        return loop_;
    }
    const std::string &name() const { return name_; }
    const InetAddress &localAddr() const { return localAddr_; }
    const InetAddress &peerAddr() const { return peerAddr_; }
    bool connected() const { return state_ == kConnected; }
    void send(const void *meaasge, int len);
    void shutdown();

    void setConnectionCallback(const ConnectionCallback &cb) { connectionCallback_ = cb; }

    void setMessagecallback(const MessageCallback &cb) { messageCallback_ = cb; }

    void setWriteComplateCallback(const WriteCompleteCallback &cb) { writeCompleteCallback_ = cb; }

    void setCloseCallback(const CloseCallback &cb) { closeCallback_ = cb; }

    void setHighWriteMarkCallback(const HighWaterMarkCallback &cb, size_t highWaterMark)
    {
        highWaterMarkCallback_ = cb;
        highWaterMark_ = highWaterMark;
    }

    // 建立于销毁链接
    void connectionEstablished();
    void connectionDestoryed();
    void send(const std::string &buf);
    void shutdownInLoop();
    void sendInLoop(const void *message, size_t len);

private:
    enum StateE
    {
        kDisconnected,
        kConnecting,
        kConnected,
        kDisconnecting
    };

    void setstate(StateE state) { state_ = state; }
    void handleRead(TimeStamp receiveTime);
    void handleWrite();
    void handleClose();
    void handleError();

    EventLoop *loop_; // 这里的Loop一定是subloop而不是basicloop
    const std::string name_;
    std::atomic_int state_;
    bool reading_;

    std::unique_ptr<Socket> socket_;
    std::unique_ptr<Channel> channel_;

    const InetAddress localAddr_;
    const InetAddress peerAddr_;

    ConnectionCallback connectionCallback_;
    MessageCallback messageCallback_;
    WriteCompleteCallback writeCompleteCallback_;
    HighWaterMarkCallback highWaterMarkCallback_;
    CloseCallback closeCallback_;
    size_t highWaterMark_;

    Buffer inputBuffer_;
    Buffer outputBuffer_;
};